//	--------------------------------------------------------------------
//	Copyright(C) 2006,2007 Zhao Yukun. All rights reserved.
//	This file is a part of the Xeres system.
//	Xeres 2007
//	Contact : xeres.engine@gmail.com
//	$(reservedInfo)
//	$(reservedDeclaration)
//	--------------------------------------------------------------------
///	@file	<xml_parser.h>
///	@path	~/src/database/xdata/
///	@date	2007/12/04
///	@desc	Encapsulates a simple XML parser.

#pragma once

#include "xeres.h"

#include "object/IBuffer.h"
#include "object/varying_data.h"

#include "database/database.h"
#include "database/store/IFile.h"
#include "database/store/cached_file.h"

namespace xeres {

	// document encoding
	enum XmlEncoding
	{
		XML_ENCODING_UNKNOWN = 0 ,
		XML_ENCODING_MBS = 1 ,
		XML_ENCODING_UTF8 = 2 ,
		XML_ENCODING_last
	};

	/*!
		\class	XmlParser
		\brief	A simple XML parser.
	*/
	class XmlParser
	{
	public:

		/// \ctor
		XmlParser( void );

		/// \dtor
		virtual ~XmlParser( void );

	//@ interface

		/*!
			\brief		Call while parsing element and step in.
		*/
		virtual bool OnElementBegin( const WString& element ) = 0;

		/*!
			\brief		Call while parsing element attribute.
		*/
		virtual bool OnAttribute( const WString& name , const WString& attr ) = 0;

		/*!
			\brief		Call while parsing element value.
		*/
		virtual bool OnValue( const WString& data ) = 0;


		/*!
			\brief		Call while parsing element end.
		*/
		virtual bool OnElementEnd( void ) = 0;


	//@ local

		/*!
			\brief		Parse XML from a file.
		*/
		bool ParseFile( RefWeak<IFile> file );

		/*!
			\brief		Parse XML from a string.
		*/
		bool ParseString( const byte * data );

	private:

		enum NodeType
		{
			NODE_ERROR ,
			NODE_DECLARATION ,
			NODE_COMMENT ,
			NODE_ELEMENT ,
			NODE_ATTRIBUTE ,
			NODE_CDATA ,
			NODE_last
		};

		// identify what node we're going into
		template< typename _Pointer > NodeType Identify( _Pointer& ptr );

		// skip white space from current position.
		template< typename _Pointer > void SkipWhitespace( _Pointer& ptr );

		// read identifier
		template< typename _Pointer > bool ReadIdentifier( _Pointer& ptr , WString& name );

		// read text
		template< typename _Pointer > bool ReadText( _Pointer& ptr , WString& text ,
			const char * endTag , bool trimWhiteSpace , bool caseInsensitive , bool eatEndTag );

		// read value
		template< typename _Pointer > bool ReadValue( _Pointer& ptr , WString& value );

		// parse comment
		template< typename _Pointer > bool ParseComment( _Pointer& ptr );

		// parse cdata
		template< typename _Pointer > bool ParseCDATA( _Pointer& ptr , std::vector<byte>& cdata );

		// parse text
		template< typename _Pointer > bool ParseText( _Pointer& ptr , WString& text );

		// parse attribute
		template< typename _Pointer > bool ParseAttribute( _Pointer& ptr , WString& attr , WString& data );

		// parse element
		template< typename _Pointer > bool ParseElement( _Pointer& ptr );

		// parse decl
		template< typename _Pointer > bool ParseDeclaration( _Pointer& ptr );

		// parse document
		template< typename _Pointer > bool ParseDocument( _Pointer& ptr );

	//@ data
		XmlEncoding		m_encoding;
	};

} // namespace xeres
